package com.kun.base.shiro;

import com.kun.base.model.User;
import com.kun.base.redis.RedisClient;
import com.kun.base.shiro.dao.ShiroDao;
import com.kun.base.shiro.model.Role;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.subject.WebSubject;
import org.springframework.beans.factory.annotation.Autowired;

import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.*;

/**
 * Created by likun on 2016/8/12 0012.
 */
public class MyRealm extends AuthorizingRealm{

    @Autowired
    private ShiroDao shiroDao;

    /**
     * 授权
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        User shiroUser = (User) principalCollection.getPrimaryPrincipal();
        if (shiroUser != null) {
            SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();

//            HttpSession httpSession = getSession();
//            Set<String> permissions=(Set<String>)httpSession.getAttribute("shiroStringPermissions");
//            Set<String> roleList=(Set<String>)httpSession.getAttribute("shiroRoles");
            RedisClient<Set<String>> redisClient=new RedisClient<Set<String>>();
            Set<String> permissions=redisClient.get("user:user_permissions_"+shiroUser.getId());
            Set<String> roleList=redisClient.get("user:user_roles_"+shiroUser.getId());
            if (permissions==null){
                // 获取用户角色
                int userId = shiroUser.getId();
                List<Integer> roleIds = shiroDao.findRoleIdsByUser(userId);
                if (roleIds == null && roleIds.isEmpty()) {
                    throw new RuntimeException("登录超时,或您没有权限访问该页面");
                }
                List<Role> roles = shiroDao.findRolesById(roleIds);
                boolean isSuper = false;
                Set<String> resourceUrls = new HashSet<String>();
                for (Role role : roles) {
                    info.addRole(role.getName());
                    if ("超级管理员".equals(role.getName())) {
                        isSuper = true;
                        // 所有权限
                        info.addStringPermission("*");
                        break;
                    }
                    // 获取用户所拥有的功能集合
                    List<String> urls = shiroDao.findResourceUrlsByRole(role.getId());
                    resourceUrls.addAll(urls);
                }

                if (!isSuper) {
                    // 设置用户所拥有的功能集合
                    Iterator<String> iterator = resourceUrls.iterator();
                    String windowLine = "\r\n";
                    String linuxLine = "\n";
                    while (iterator.hasNext()) {
                        String url = iterator.next();
                        if (url != null && url != "") {
                            //把\r缓存\n,解决根据\n分隔之后,某些url带有 /per/xxx\r的情况。
                            String[] urls;
                            if (url.indexOf(windowLine) != -1) {
                                urls = url.split(windowLine);
                            } else {
                                urls = url.split(linuxLine);
                            }
                            info.addStringPermissions(Arrays.asList(urls));
                        }
                    }
                }
                Set<String> shiroRoles = info.getRoles();
                Set<String> shiroStringPermissions = info.getStringPermissions();
                redisClient.set("user:user_permissions_"+shiroUser.getId(),shiroStringPermissions);
                redisClient.set("user:user_roles_"+shiroUser.getId(),shiroRoles);
//                httpSession.setAttribute("shiroRoles",shiroRoles);
//                httpSession.setAttribute("shiroStringPermissions",shiroStringPermissions);
            }else {
                info.addRoles(roleList);
                info.addStringPermissions(permissions);
            }
            return info;
        }
        return null;
    }

    /**
     * 认证
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
        // 通过表单接收的用户名
        String username = token.getUsername();

        if (username == null || "".equals(username)) {
            throw new UnknownAccountException();
        }

        // 通过登录名称查询用户信息
        User user = shiroDao.findByUsername(username);

        if (user != null) {
            getSession().setAttribute("user",user);//缓存当前用户信息
            return new SimpleAuthenticationInfo(user, user.getPassword(), getName());
        }
        throw new UnknownAccountException();
    }

    private void setSession(Object key, Object value){
        Subject currentUser = SecurityUtils.getSubject();
        if(null != currentUser){
            Session session = currentUser.getSession();
            System.out.println("Session默认超时时间为[" + session.getTimeout() + "]毫秒");
            if(null != session){
                session.setAttribute(key, value);
            }
        }
    }

    public static HttpSession getSession(){
        ServletRequest request = ((WebSubject)SecurityUtils.getSubject()).getServletRequest();
        HttpSession httpSession = ((HttpServletRequest)request).getSession();
        return httpSession;
    }
}
